// resolve 用来拼接绝对路径的方法
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 提取css为单独文件，而并非打包到html中去
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 压缩css的插件
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');

const WorkboxWebpackPlugin = require('workbox-webpack-plugin');

// html-webpack-plugin
// new HtmlWebpackPlugin()   功能：默认会创建一个空的html文件，不会自动引入打包输出的所有资源（js/css）
const htmlWebpackPlugin = new HtmlWebpackPlugin({
    // 复制 './src/index.html' 文件，并自动引入打包输出的所有资源（js/css）
    template: './src/index.html',
    // 重命名
    // filename: 'index.html',
    minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true,
    }
});

const miniCssExtractPlugin = new MiniCssExtractPlugin({
    // 对输出的css文件进行重命名
    filename: 'css/built.[hash:10].css'
});

const optimizeCssAssetsPlugin = new OptimizeCssAssetsPlugin();

const workboxWebpackPlugin = new WorkboxWebpackPlugin.GenerateSW({
    // 帮组 serviceworker 快速启动
    // 删除旧的 serviceworker 
    // 该插件会帮我们生产 serviceworker 的一个配置文件
    clientsClaim: true,
    skipWaiting: true,
});

// 处理css和less都需要的loader处理器
const commonCssLoader = [
    MiniCssExtractPlugin.loader,  // 这个loader取代 style-loader .作用：提取js中的css成单独文件
    'css-laoder', // 将css文件变成 commonjs 模块加载到js中，里面内容是样式字符串
    {
        // 还需要在 package.json 中定义 browserslist
        loader: 'postcss-loader',
        options: {
            ident: 'postcss',
            plugins: () => [require('postcss-preset-env')]
        }
    }
]

const myEnv = 'production';

// 对 node 环境的配置
process.env.NODE_ENV = myEnv;
// webpack 配置
const webPackConfig = {

    // 入口起点
    entry: './src/js/index.js',
    output: {
        // 输出文件名
        filename: 'js/build.[hash:10].js',
        // __dirname 是nodejs的变量，代表当前文件的目录的绝对路径,相当于【./】
        // resolve(__dirname,'build') 方法就相当于将这两个目录拼接起来
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [
            // js eslint
            {
                test: /\.js$/,
                exclude: /node_modules/,
                // 正常来讲，一个文件只能被一个loader处理。
                // 当一个文件要被多个loader处理时，那么一定要指定loader执行的先后顺序： enforce: 'pre' 【优先执行】
                enforce: 'pre',
                loader: 'eslint-loader',
                options: {
                    // 自动修改eslint的相关格式
                    fix: true
                }
            },
            {
                // oneOf 表示一下loader只会匹配一个
                // 注意： 不能有两个配置处理同一种类型文件，当必须有多个配置的话可以将其它多的配置提到上面一层级
                oneOf: [
                    // css 处理
                    {
                        test: /\.css$/,
                        use: [...commonCssLoader]
                    },
                    // less 处理
                    {
                        test: /\.less$/,
                        use: [...commonCssLoader, 'less-loader']
                    },
                    // js 按需解决兼容问题
                    {
                        test: /\.js$/,
                        exclude: /node_modules/,
                        use: [
                            /*
                                开启多线程打包，有利有弊的
                                线程启动大概为 600ms ,线程通信也有开销
                                一般来说工作时间消耗时间比较长，才会需要多线程打包
                            */
                            {
                                loader:'thread-loader',
                                options: {
                                    workers :2 // 线程2两个
                                }
                            }, 
                            {
                                loader: 'babel-loader',
                                options: {
                                    presets: [
                                        [
                                            '@babel/preset-env',
                                            {
                                                // 按需加载
                                                useBuiltIns: 'usage',
                                                // 指定 core-js 版本
                                                corejs: {
                                                    version: 3
                                                },
                                                // 指定具体的兼容到那个版本的浏览器
                                                targets: {
                                                    chrome: '60',
                                                    firefox: '60',
                                                    ie: '9',
                                                    safari: '10',
                                                    edge: '17',
                                                }
                                            }
                                        ]
                                    ],
                                    cacheDirectory: true
                                }
                            }
                        ],

                    },
                    // 图片处理
                    {
                        // test: /\.(jpg|png|gif|bmp|ttf|eot|svg|woff|woff2)/,
                        test: /\.(jpg|png|gif)/,
                        // 注：【当loader只有一个时可以使用方式二的模式写，如果有多个并且有不同的参数可以使用方式一】
                        // 方式一配置
                        // use: ['url-loader?limit=8192&esModule=false&name=[hash:10].[ext]']
                        // 方式二配置
                        loader: 'url-loader',
                        options: {
                            // 图片大小小于8kb，就会被base64处理
                            // 优点：减少请求数量【减轻服务器压力】
                            // 缺点：图片体积会更大【文件请求速度更慢】
                            limit: 8 * 1024,
                            // 问题：因为url-loader默认使用es6模块化解析，而html-loader引入图片是commonjs
                            // img 标签进行解析时就会出现 src="[object Module]"
                            // 解决方案：关闭 url-loader 的es6模块化,使用commonjs来进行解析
                            esModule: false,
                            // 给图片进行重命名
                            // [hash:10] 取图片的hash值的前10位
                            // [ext] 取文件原来扩展名
                            name: '[hash:10].[ext]',
                            // 将图片输出到该文件夹下面
                            outputPath: 'imgs'
                        }
                    },
                    // html 处理
                    {
                        test: /\.html$/,
                        loader: 'html-loader' // 处理html文件中的img图片，【负责引入img,从而能被url-loader进行处理】
                    },
                    // 处理其他文件
                    {
                        exclude: /\.(js|css|less|html|jpg|png|gif)/,
                        loader: 'file-loader',
                        options: {
                            // 将其它文件输出到该文件夹下面
                            outputPath: 'media'
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        htmlWebpackPlugin,
        miniCssExtractPlugin,
        optimizeCssAssetsPlugin,
        workboxWebpackPlugin,
    ],
    // mode: 'development', // 开发模式
    mode: 'production', // 生产模式  会自动压缩js代码

    // 开发服务器 devServer ： 用来自动化【自动编译，自动打开浏览器，自动刷新】
    // 只会在内存中编译打包，不会有任何输出
    // 启动devServer指令： npx webpack-dev-server 
    devServer: {
        contentBase: resolve(__dirname, 'build'),
        // 启动gzip压缩
        compress: true,
        // 端口号
        port: 3000,
        // 是否自动打开默认浏览器
        open: false
    },
    devtool: 'source-map'

}

module.exports = webPackConfig


/**
 * 多线程打包 需要下载  npm i thread-loader -D
 *
 * thread-loader 一般用于 babel-loader
 *
 */